import DeleteFilled from "@ant-design/icons/DeleteFilled"
import EditFilled from "@ant-design/icons/EditFilled"
import { Option, OptionValue } from "@mallfoundry/catalog"
import { Button, Col, Divider, Form, Input, Row } from "antd"
import * as _ from "lodash"
import * as React from "react"
import { useEffect, useState } from "react"
import classes from "./product-options.module.scss"

interface ProductOptionValueProps {
  value: OptionValue;
  editable?: boolean;
  otherLabels: string[]
  onDelete?: (value: OptionValue) => void;
  onChange: (value: OptionValue) => void;
}

function ProductOptionValue(props: ProductOptionValueProps) {
  const { value, otherLabels, onChange, onDelete } = props
  const [label, setLabel] = useState(value.label)
  const [editable, setEditable] = useState(props.editable)
  const [labelEmpty, setLabelEmpty] = useState(false)
  const [labelExists, setLabelExists] = useState(false)

  function onChangeValue(aLabel: string) {
    const empty = _.isEmpty(aLabel)
    setLabelEmpty(empty)
    if (!empty) {
      console.log(otherLabels, aLabel)
      const labelIncluded = _.includes(otherLabels, aLabel)
      setLabelExists(labelIncluded)
      if (!labelIncluded) {
        setEditable(false)
        onChange(_.assign(new OptionValue(), value, { label: aLabel }))
      }
    }
  }

  function labelHelp() {
    if (labelExists) {
      return "选项值已存在"
    }
    return undefined
  }

  return (
    <>
      {!editable && <div className={classes.optionValue}>
        <span className={classes.optionValueText}>{label}</span>
        <EditFilled onClick={(e: React.MouseEvent<HTMLElement>) => {
          e.stopPropagation()
          setEditable(!editable)
        }}/>
        <Divider type="vertical"/>
        <DeleteFilled onClick={(e: React.MouseEvent<HTMLElement>) => {
          e.stopPropagation()
          if (_.isFunction(onDelete)) {
            onDelete(_.assign(new OptionValue(), value, { label }))
          }
        }}/>
      </div>}
      {editable &&
      <Form.Item className={classes.optionValueFormItem}
                 validateStatus={labelEmpty || labelExists ? "error" : "success"}
                 help={labelHelp()}>
        <Input.Search placeholder="请输入选项值" enterButton="确定" value={label}
                      onChange={e => setLabel(e.target.value)}
                      onSearch={onChangeValue}/>
      </Form.Item>}
    </>
  )
}

interface ProductOptionProps {
  option: Option;
  otherNames: string[]
  onChange: (option: Option) => void;
  onDelete?: (value: Option) => void;
}

function ProductOption(props: ProductOptionProps) {
  const { option, otherNames, onChange } = props
  const { values = [], name: defaultOptionName } = option
  const allOptionLabels = _.map(values, aValue => aValue.label as string)
  // Option name state
  const [optionName, setOptionName] = useState(defaultOptionName)
  const [existsOptionName, setExistsOptionName] = useState(false)
  const nameEmpty = _.isEmpty(optionName)
  // Option value label state
  const [addNewValueLabel, setNewValueLabel] = useState("")
  const [existsNewValueLabel, setExistsNewValueLabel] = useState(false)
  const [newValueLabelEmpty, setNewValueLabelEmpty] = useState(false)
  useEffect(() => {
    setOptionName(defaultOptionName)
  }, [defaultOptionName])

  useEffect(() => {
    const optionNameIndex = _.indexOf(otherNames, optionName)
    setExistsOptionName(optionNameIndex !== -1)
  }, [otherNames, optionName])

  function onAddValue(label: string) {
    const labelEmpty = _.isEmpty(label)
    setNewValueLabelEmpty(labelEmpty)
    if (!labelEmpty) {
      const labelExists = _.includes(allOptionLabels, label)
      setExistsNewValueLabel(labelExists)
      if (!labelExists) {
        setNewValueLabel("")
        const newValue = new OptionValue()
        newValue.label = label
        onChangeValues([...option.values as OptionValue[], newValue])
      }
    }
  }

  function onChangeValues(values: OptionValue[]) {
    option.values = values
    if (_.isFunction(props.onChange)) {
      props.onChange(option)
    }
  }

  function onChangeName(name: string) {
    option.name = name
    onChange(option)
  }

  function onDeleteValue(value: OptionValue) {
    onChangeValues(_.filter(values, aValue => aValue.label !== value.label))
  }

  function onDelete(value: Option) {
    if (_.isFunction(props.onDelete)) {
      props.onDelete(value)
    }
  }

  function nameHelp() {
    if (existsOptionName) {
      return "选项名不能重复"
    }
    return undefined
  }

  function newLabelHelp() {
    if (existsNewValueLabel) {
      return "选项值已存在"
    }
    return undefined
  }

  return (
    <>
      <Row justify="space-between" align="middle" className={classes.optionName}>
        <Col span={6}>
          <Form.Item validateStatus={nameEmpty || existsOptionName ? "error" : "success"} help={nameHelp()}>
            <Input value={optionName} placeholder="请输入选项名"
                   onChange={e => setOptionName(e.target.value)}
                   onBlur={e => onChangeName(e.currentTarget.value)}
                   onPressEnter={e => onChangeName(e.currentTarget.value)}/>
          </Form.Item>
        </Col>
        <Col>
          <Button type="link" onClick={() => {
            if (_.isFunction(onDelete)) {
              onDelete(option)
            }
          }}>删除选项</Button>
        </Col>
      </Row>
      <div className={classes.optionValues}>
        {_.map(values, (value, index) =>
          <ProductOptionValue key={value.label as string + index}
                              value={value}
                              editable={_.isEmpty(value.label)}
                              otherLabels={_.filter(allOptionLabels, (aLabel, aIndex) => aIndex !== index)}
                              onChange={value => {
                                values[index] = value
                                onChangeValues([...values])
                              }} onDelete={onDeleteValue}/>)
        }
      </div>
      <Row gutter={[0, 16]}>
        <Col span={12}>
          <Form.Item validateStatus={existsNewValueLabel || newValueLabelEmpty ? "error" : "success"} help={newLabelHelp()}>
            <Input.Search placeholder="请输入选项值" enterButton="添加" value={addNewValueLabel}
                          onBlur={() => {
                            setExistsNewValueLabel(false)
                            setNewValueLabelEmpty(false)
                          }}
                          onChange={e => setNewValueLabel(e.target.value)}
                          onSearch={onAddValue}/>
          </Form.Item>
        </Col>
      </Row>
    </>
  )
}

interface ProductOptionsProps {
  options: Option[];
  onChange?: (options: Option[]) => void;
}

export default function ProductOptions(props: ProductOptionsProps) {
  const { onChange, options } = props
  const allOptionNames = _.map(options, aOption => aOption.name)

  function sortOptions(options: Option[]) {
    _.forEach(options, (option: Option, index) => option.position = index)
    return options
  }

  function onAddOption() {
    const newOption = new Option()
    newOption.name = ""
    invokeOnChange(sortOptions([...options, newOption]))
  }

  function onDeleteOption(option: Option) {
    invokeOnChange(_.filter(options, (aOption: Option) => aOption.position !== option.position))
  }

  function invokeOnChange(newOptions: Option[]) {
    if (_.isFunction(onChange)) {
      onChange(newOptions)
    }
  }

  return (
    <div className={classes.productOptions}>
      {_.map(options, (option, index) =>
        <ProductOption key={option.name as string + index}
                       otherNames={_.filter(allOptionNames, (aName, aIndex) => aIndex !== index) as string[]}
                       option={option}
                       onChange={value => {
                         options[index] = value
                         invokeOnChange([...options])
                       }}
                       onDelete={onDeleteOption}/>)
      }
      <div className={classes.optionActions}>
        <Button onClick={onAddOption}>添加不同选项</Button>
      </div>
    </div>)
}
